import axios from 'axios';
import * as PdfJs from 'pdfjs-dist';
import { PDFDocumentProxy } from 'pdfjs-dist';

interface UploadImgRes {
    success: boolean;
    message: string;
    code: number;
    result: null;
    timestamp: number;
}

export default class PDFTool {
    private _url: string;
    /** 文档流 */
    file: ArrayBuffer | undefined;
    pdf: PDFDocumentProxy | undefined;
    /** pdf页数 */
    numPages = 0;

    /** pdf路径 */
    get url() {
        return `${import.meta.env.VITE_IMG_BASE_URL}${this._url}`;
    }

    constructor(url: string) {
        this._url = url;
        this.initPDFDocumentProxy();
    }
    private async initPDFDocumentProxy() {
        if (this.pdf) return;
        const buffer = await this.fetchPdfFile();
        this.file = buffer;
        this.pdf = await PdfJs.getDocument(buffer).promise;
        this.numPages = await this.getPdfNumPages();
    }
    /** 获取pdf文件 */
    private async fetchPdfFile() {
        const res = await axios.get(this.url, { responseType: 'blob' });

        const buffer = await this.blobToArrayBuffer(res.data);
        return buffer;
    }
    /** 文件类型转换 */
    private blobToArrayBuffer(file: Blob): Promise<ArrayBuffer> {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onerror = reject;
            reader.onload = () => {
                resolve(reader.result as ArrayBuffer); // reader.result 是一个 ArrayBuffer 对象
            };
            reader.readAsArrayBuffer(file); // 使用 readAsArrayBuffer 方法读取 Blob 数据
        });
    }

    /** 获取文件页码数量 */
    private async getPdfNumPages() {
        if (!this.pdf) return 0;
        return (await this.pdf.loadingTask.promise).numPages;
    }
    /** 渲染pdf */
    public async renderPdfFile(div: HTMLDivElement, pageNo = 1, scale = 1) {
        if (!this.pdf) {
            await this.initPDFDocumentProxy();
        }
        const page = await this.pdf!.getPage(pageNo);

        const defaultViewPort = page.getViewport({ scale: 1 }); // 默认宽度尺寸
        const realScale = div.clientWidth / defaultViewPort.width; // 计算默认宽度比例

        const viewport = page.getViewport({ scale: scale * realScale });

        const canvas = document.createElement('canvas');

        canvas.width = viewport.width;
        canvas.height = viewport.height;
        div.appendChild(canvas);
        // 将PDF页面渲染到<canvas>元素中
        page.render({
            canvasContext: canvas.getContext('2d')!,
            viewport: viewport,
        });
        return canvas;
    }

    /** 渲染全部pdf */
    public async renderPdfAllPage(div: HTMLDivElement, scale = 1) {
        if (!this.pdf || !this.numPages) {
            await this.initPDFDocumentProxy();
        }

        for (let page = 1; page <= this.numPages; page += 1) {
            const canvas = document.createElement('div');
            canvas.style.width = `${div.clientWidth}px`;
            this.renderPdfFile(canvas, page, scale);
            div.appendChild(canvas);
        }
        return div;
    }

    /** 上传pdf封面 */
    public async uploadPdfCover() {
        if (!this.pdf) {
            await this.initPDFDocumentProxy();
        }

        const page = await this.pdf!.getPage(1);
        const viewport = page.getViewport({ scale: 1 });
        const canvas = document.createElement('canvas');
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        await page.render({
            canvasContext: canvas.getContext('2d')!,
            viewport: viewport,
        }).promise;

        const Upload_Url = import.meta.env.VITE_APP_API + '/sys/common/upload';
        const dataURL = canvas.toDataURL('image/jpeg');
        const dataBlob = this.dataURLtoBlob(dataURL);
        const file = new File([dataBlob], 'pdf封面.jpeg');
        const res = await axios.post<UploadImgRes>(
            Upload_Url,
            { file },
            {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            },
        );
        return res.data;
    }

    /**
     * Base64字符串转二进制流
     * @param {String} dataurl Base64字符串(字符串包含Data URI scheme，例如：data:image/png;base64, )
     */
    private dataURLtoBlob(dataurl: string) {
        var arr = dataurl.split(','),
            mime = arr[0].match(/:(.*?);/)![1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], {
            type: mime,
        });
    }

    /** 设置全局线程路径 */
    public static setGlobalWorkerSrc() {
        PdfJs.GlobalWorkerOptions.workerSrc = '/pdf.worker.mjs';
    }
}
